﻿
using MongoDB.Bson;
using MongoDB.Driver;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;

namespace QuestionInvestig.MongoHelper
{
    /// <summary>
    /// MongoDB数据库对象
    /// </summary>
    public class Mongo
    {
        public virtual IMongoDatabase db()
        {
            try
            {
                string connectionString = @"mongodb://10.101.40.32:27017/QuestionInvestig";
                //string connectionString = CommonConfig.Get("MonGoConnection");
                MongoUrl u = new MongoUrl(connectionString);
                var client = new MongoClient(u);
                var database = client.GetDatabase(new MongoUrl(connectionString).DatabaseName);
                return database;
            }
            catch (Exception ex)
            {
                //SkyNetHelper.ERROR("Mongodb链接异常：" + ex.ToString(), "IMongoDatabase");
                return null;
            }
        }

        /// <summary>
        /// 获取操作对象的MongoCollection集合,强类型对象集合
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        /// <param name="dbName">表名</param>
        /// <returns></returns>
        protected virtual IMongoCollection<T> GetCollection<T>(T obj, string dbName)
        {
            try
            {
                IMongoDatabase database = db();
                return database.GetCollection<T>(dbName);
            }
            catch (Exception ex)
            {
                //SkyNetHelper.ERROR(ex.ToString(), "GetCollection");
                return null;
            }
        }

        protected virtual IMongoCollection<T> GetMongoCollection<T>(string dbName)
        {
            IMongoDatabase database = db();
            return database.GetCollection<T>(dbName);
        }

        #region 添加
        /// <summary>
        /// 添加
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        /// <param name="dbName">表名</param>
        public virtual void Insert<T>(T obj, string dbName)
        {
            try
            {
                GetCollection(obj, dbName).InsertOne(obj);
            }
            catch (Exception ex)
            {
                //SkyNetHelper.ERROR(ex.ToString(), "Insert");
            }
        }

        public virtual async Task InsertAsync<T>(T obj, string dbName)
        {
            await GetCollection(obj, dbName).InsertOneAsync(obj);
        }

        /// <summary>
        /// 添加集合数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        /// <param name="list"></param>
        /// <param name="dbName"></param>
        public virtual void InsertMany<T>(T obj, List<T> list, string dbName)
        {
            GetCollection(obj, dbName).InsertMany(list);
        }

        public virtual async Task InsertManyAsync<T>(T obj, List<T> list, string dbName)
        {
            await GetCollection(obj, dbName).InsertManyAsync(list);
        }
        #endregion

        /// <summary>
        /// 查询数据
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="obj"></param>
        /// <param name="dbName">表名</param>
        /// <param name="filter">查询条件</param>
        /// <returns></returns>
        public virtual List<T> Find<T>(T obj, string dbName, FilterDefinition<T> filter)
        {
            return GetCollection(obj, dbName).Find(filter).ToList();
        }

        /// <summary>
        /// 查询数据
        /// </summary>
        /// <param name="dbName">表名</param>
        /// <param name="filter">查询条件</param>
        /// <returns></returns>
        public virtual List<BsonDocument> Find(string dbName, FilterDefinition<BsonDocument> filter)
        {
            try
            {
                return GetCollection(new BsonDocument(), dbName).Find(filter).ToList();
            }
            catch (Exception ex)
            {
                //SkyNetHelper.ERROR("Mongo查询异常：" + ex.ToString(), "MongoFind");
                return null;
            }
        }

        /// <summary>
        /// 带有排序
        /// </summary>
        /// <param name="dbName"></param>
        /// <param name="filter"></param>
        /// <param name="sort"></param>
        /// <returns></returns>
        public virtual List<BsonDocument> Find(string dbName, FilterDefinition<BsonDocument> filter, SortDefinition<BsonDocument> sort)
        {
            try
            {
                return GetCollection(new BsonDocument(), dbName).Find(filter).Sort(sort).ToList();
            }
            catch (Exception ex)
            {
                //SkyNetHelper.ERROR("Mongo查询异常：" + ex.ToString(), "MongoFind");
                return null;
            }
        }

        /// <summary>
        /// 返回表里面第一条数据
        /// </summary>
        /// <param name="dbName">表名</param>
        /// <returns></returns>
        public virtual BsonDocument Find(string dbName)
        {
            try
            {
                return GetCollection(new BsonDocument(), dbName).Find(new BsonDocument()).FirstOrDefault();
            }
            catch (Exception ex)
            {
                //SkyNetHelper.ERROR(ex.ToString(), "FindFirstOrDefault");
                return null;
            }
        }

        /// <summary>
        /// 查询数据带排序
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        /// <param name="dbName">表名</param>
        /// <param name="filter">查询条件</param>
        /// <param name="sort">排序模板</param>
        /// <returns></returns>
        public virtual List<T> Find<T>(T obj, string dbName, FilterDefinition<T> filter, SortDefinition<T> sort)
        {
            return GetCollection(obj, dbName).Find(filter).Sort(sort).ToList();
        }

        /// <summary>
        ///  查询数据(不查_id)
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="dbName"></param>
        /// <param name="filter"></param>
        /// <returns></returns>
        public virtual T Find<T>(string dbName, FilterDefinition<T> filter)
        {
            var projection = Builders<T>.Projection.Exclude("_id");
            return GetMongoCollection<T>(dbName).Find(filter).Project<T>(projection).ToList().FirstOrDefault();
        }

        /// <summary>
        ///  查询数据带排序(不查_id)
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="dbName"></param>
        /// <param name="filter"></param>
        /// <param name="sort"></param>
        /// <returns></returns>
        public virtual List<T> Find<T>(string dbName, FilterDefinition<T> filter, SortDefinition<T> sort)
        {
            var projection = Builders<T>.Projection.Exclude("_id");
            return GetMongoCollection<T>(dbName).Find(filter).Project<T>(projection).Sort(sort).ToList();
        }

        /// <summary>
        ///  查询数据带排序分页(不查_id)
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="dbName"></param>
        /// <param name="filter"></param>
        /// <param name="sort"></param>
        /// <param name="startNumber">如果第一页传0</param>
        /// <param name="pageSize">查询条数</param>
        /// <returns></returns>
        public virtual List<T> Find<T>(string dbName, FilterDefinition<T> filter, SortDefinition<T> sort,int startNumber,int pageSize)
        {
            var projection = Builders<T>.Projection.Exclude("_id");
            return GetMongoCollection<T>(dbName).Find(filter).Project<T>(projection).Sort(sort).Skip(startNumber).Limit(pageSize).ToList();
        }

        /// <summary>
        /// 查询行数
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="dbName"></param>
        /// <param name="filter"></param>
        /// <returns></returns>
        public virtual long FindCount<T>(string dbName, FilterDefinition<T> filter)
        {
            return GetMongoCollection<T>(dbName).Find(filter).Count();
        }

        /// <summary>
        /// 更新数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        /// <param name="dbName"></param>
        /// <param name="filter">更新查询数据</param>
        /// <param name="update">更新模板</param>
        /// <returns>返回更新是否成功</returns>
        public virtual bool Update<T>(T obj, string dbName, FilterDefinition<T> filter, UpdateDefinition<T> update)
        {
            return GetCollection(obj, dbName).UpdateMany(filter, update).IsAcknowledged;
        }

        public virtual bool Update<T>(string dbName, FilterDefinition<T> filter, UpdateDefinition<T> update)
        {
            return GetMongoCollection<T>(dbName).UpdateMany(filter, update).IsAcknowledged;
        }
    }
}
